<!--
 * @Author: Z.MingYu
 * @Date: 2025-05-15 16:15:31
 * @Description: ez-table 主文件
-->
<template>
  <div class="ez-table-wrapper" :style="tableCss" :class="tableCls">
    <div class="header-container">
      <div class="header-fixed-container">
        <table-header
          class="header-fixed-table"
          :columns="fixedCols"
          :header="customHeader.fixed"></table-header>
      </div>
      <div class="header-static-container" ref="headerStatic">
        <table-header
          class="header-static-table"
          :columns="staticCols"
          :header="customHeader.static"></table-header>
      </div>
    </div>
    <div class="body-container">
      <div class="body-fixed-container" ref="bodyFixed">
        <table-body class="body-fixed-table" :columns="fixedCols" :dataset="dataset"></table-body>
      </div>
      <div class="body-static-container" ref="bodyStatic">
        <table-body class="body-static-table" :columns="staticCols" :dataset="dataset"></table-body>
      </div>
    </div>
  </div>
</template>

<script>
import { Options, Column, UnitPaths } from './define';
import { isNull, isEmpty, isNumber, merge } from './tableUtils';
import tableHeader from './tableHeader.vue';
import tableBody from './tableBody.vue';
export default {
  name: 'ez-table-vue',
  components: { tableHeader, tableBody },
  props: {
    options: {
      type: Object,
      default: () => ({})
    },
    columns: {
      type: Array[Object],
      required: true
    },
    dataset: {
      type: Array[Object],
      default: () => []
    },
    customHeader: {
      type: Object,
      default: () => ({})
    }
  },
  data() {
    return {};
  },
  mounted() {
    this.initScrollEvent();
  },
  computed: {
    defUnit() {
      return this.options.unit ?? 'px';
    },
    tableOpts() {
      const opts = merge(Options, this.options);
      this.formatOptsUnit(opts);
      return opts;
    },
    tableCss() {
      const table = this.tableOpts.table;
      const header = this.tableOpts.header;
      const body = this.tableOpts.body;
      return {
        '--ezt-t-b-width': table.border.width,
        '--ezt-t-b-color': table.border.color,
        '--ezt-h-background': header.background,
        '--ezt-h-b-width': header.border.width,
        '--ezt-h-b-color': header.border.color,
        '--ezt-h-shadow-width': header.shadow.width,
        '--ezt-h-shadow-color': header.shadow.color,
        '--ezt-h-r-height': header.row.height,
        '--ezt-h-c-align': header.cell.align,
        '--ezt-h-c-padd-left': header.cell.paddLeft,
        '--ezt-h-c-padd-right': header.cell.paddRight,
        '--ezt-h-c-font-size': header.cell.fontSize,
        '--ezt-b-b-width': body.border.width,
        '--ezt-b-b-color': body.border.color,
        '--ezt-b-shadow-width': body.shadow.width,
        '--ezt-b-shadow-color': body.shadow.color,
        '--ezt-b-r-height': body.row.height,
        '--ezt-b-c-align': body.cell.align,
        '--ezt-b-c-padd-left': body.cell.paddLeft,
        '--ezt-b-c-padd-right': body.cell.paddRight,
        '--ezt-b-c-font-size': body.cell.fontSize,
        '--ezt-b-h-color': body.hover.color,
        '--ezt-b-s-color': body.stripe.color,
        '--ezt-fixed-cols-width': this.fixedColsWidth
      };
    },
    tableCls() {
      const cls = [];
      if (this.tableOpts.body.hover.used) cls.push('hoverd');
      if (this.tableOpts.body.stripe.used) cls.push('striped');
      return cls;
    },
    tableCols() {
      return this.columns.map(col => {
        const c = merge(Column, col);
        if (isNull(c.name)) console.error('列配置错误：缺少 name 列名标识！');
        if (isEmpty(c.title)) c.title = c.name;
        if (isEmpty(c.width) && c.fixed) c.width = this.tableOpts.header.cell.defWidth;
        c.width = this.formatUnit(c.width);
        return c;
      });
    },
    fixedCols() {
      return this.tableCols.filter(col => col.fixed);
    },
    fixedColsWidth() {
      const width = this.fixedCols.reduce((sum, col) => {
        return sum + parseInt(col.width);
      }, 0);
      return `${width}${this.defUnit}`;
    },
    staticCols() {
      return this.tableCols.filter(col => !col.fixed);
    }
  },
  methods: {
    initScrollEvent() {
      const headerStatic = this.$refs.headerStatic;
      const bodyFixed = this.$refs.bodyFixed;
      const bodyStatic = this.$refs.bodyStatic;
      headerStatic.addEventListener('scroll', evt => {
        const left = evt.target.scrollLeft;
        bodyStatic.scrollTo({ left });
      });
      bodyFixed.addEventListener('scroll', evt => {
        const top = evt.target.scrollTop;
        bodyStatic.scrollTo({ top });
      });
      bodyStatic.addEventListener('scroll', evt => {
        const left = evt.target.scrollLeft;
        const top = evt.target.scrollTop;
        headerStatic.scrollTo({ left });
        bodyFixed.scrollTo({ top });
      });
    },
    formatOptsUnit(opts) {
      UnitPaths.forEach(path => this.formatOptUnit(opts, path));
    },
    formatOptUnit(opts, path) {
      const paths = path.split('.');
      const lastInd = paths.length - 1;
      let curr = opts;
      for (let i = 0; i < lastInd; i++) curr = curr[paths[i]];
      curr[paths[lastInd]] = this.formatUnit(curr[paths[lastInd]]);
    },
    formatUnit(v) {
      if (isNull(v)) return 'auto';
      return isNumber(v) ? `${parseInt(v)}${this.defUnit}` : v;
    }
  }
};
</script>

<style scoped>
@import './style.scss';
</style>
